package com.zmm.book.keep.controller;

import com.zmm.book.keep.model.Bill;
import com.zmm.book.keep.model.Mode;
import com.zmm.book.keep.model.Source;
import com.zmm.book.keep.model.Type;
import com.zmm.book.keep.service.BillService;
import com.zmm.book.keep.service.ModeService;
import com.zmm.book.keep.service.MonthBillService;
import com.zmm.book.keep.service.SourceService;
import com.zmm.book.keep.service.TypeService;
import com.zmm.book.keep.vo.BillConsumeDetailVo;
import com.zmm.book.keep.vo.BillResultVo;
import com.zmm.book.keep.vo.DetailParamVo;
import com.zmm.book.keep.vo.MonthBillVo;
import com.zmm.book.keep.vo.SearchVo;
import com.zmm.common.base.model.Paging;
import com.zmm.common.base.model.Query;
import com.zmm.common.base.model.ResponseResult;
import com.zmm.common.base.model.Result;
import com.zmm.common.base.model.ResultCode;
import com.zmm.common.redis.key.CommonKey;
import com.zmm.common.valid.AddGroup;
import com.zmm.common.valid.UpdateGroup;
import com.zmm.util.auth.model.Operator;
import com.zmm.util.auth.model.UserForAuth;
import com.zmm.util.auth.registry.annotation.AuthAnonymous;
import com.zmm.util.document.register.Interface;
import com.zmm.util.document.register.Param;
import com.zmm.util.redis.RedisUtil;
import com.zmm.util.verify.BindingResultUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import java.util.List;

/**
 * @author 900045
 * @description:
 * @name BillController
 * @date By 2021-09-28 10:13:31
 */
@Controller
@Slf4j
@RequestMapping("/bill")
public class BillController {
	
	@Resource
	private Operator operator;
	
	@Resource
	private RedisUtil redisUtil;
	
	@Resource
	private BillService billService;

	@Resource
	private ModeService modeService;

	@Resource
	private TypeService typeService;
	
	@Resource
	private SourceService sourceService;
	
	@Resource
	private MonthBillService monthBillService;

	@RequestMapping(value = "/to/statistics",method = RequestMethod.GET)
	public String statistics(Model model, Paging page, String date){
		// 查询用户
		UserForAuth userForAuth = operator.userOrNull();
		MonthBillVo monthBillVo = new MonthBillVo();
		monthBillVo.setCustomerId(userForAuth.getUserId());
		monthBillVo.setMonth(date);
		Query<MonthBillVo> queryMonthBill = new Query(page);
		queryMonthBill.setCondition(monthBillVo);
		monthBillService.queryMonthBillList(queryMonthBill);
		model.addAttribute("queryMonthBill", queryMonthBill);
		model.addAttribute("date", date);
		return "month_bill_statistics";
	}

	/**
	 * 去这个账单首页
	 * author: 900045
	 * date: 2021-09-28 10:15:09
	 * throws 
	 * return: java.lang.String
	 **/
	@AuthAnonymous
	@RequestMapping(value = "/to/index",method = RequestMethod.GET)
	public String toIndex(Model model, Paging page, SearchVo searchVo){
		// 查询用户
		UserForAuth userForAuth = operator.userOrNull();
		setModel(model, page, searchVo, userForAuth);
		return "bill_index";
	}

	@AuthAnonymous
	@RequestMapping(value = "/to/index2",method = RequestMethod.GET)
	public String toIndex2(Model model, Paging page, SearchVo searchVo){
		String token = searchVo.getToken();
		if (StringUtils.isEmpty(token)) {
			return "bill_index";
		}
		Object object = getUserFromRedis(token);
		if (object == null){
			return "bill_index";
		}
		UserForAuth user = (UserForAuth) object;
		if (ObjectUtils.isEmpty(user)) {
			return "bill_index";
		}
		// 3.放入userId 到当前线程
		operator.addThread(user);
		setModel(model, page, searchVo, user);
		//model.addAttribute("customerId",user.getUserId())
		return "bill_index";
	}

	/**
	 * 包装 Model 对象
	 * author: 900045
	 * date: 2021-10-11 11:38:27
	 * throws 
	 * @param model: 
	 * @param page: 
	 * @param searchVo: 
	 * @param user: 
	 * return: void
	 **/
	private void setModel(Model model, Paging page, SearchVo searchVo, UserForAuth user) {
		model.addAttribute("userForAuth", user);
		// 查询账单记录
		Query<BillResultVo> queryBill = new Query(page);
		if (!ObjectUtils.isEmpty(user)) {
			searchVo.setCustomerId(operator.fetchUserId());
			queryBill.setCondition(searchVo);
			billService.queryBillList(queryBill);
		}
		model.addAttribute("queryBill", queryBill);
		model.addAttribute("token",searchVo.getToken());
	}

	private Object getUserFromRedis(String token){
		Object key = redisUtil.get(CommonKey.AUTH_TOKEN_USER_PREFIX.setSuffix(token));
		if (key != null) {
			Object o = redisUtil.hash(CommonKey.AUTH_USER_KEY, key);
			if (o == null) {
				return null;
			}
			return o;
		}
		return null;
	}

	/**
	 * 未登陆时 查询账单
	 * description:
	 * author: Zebulon
	 * date: 2021-10-10 18:26:35
	 * @param model: 
	 * @param page: 
	 * @param searchVo: 
	 * return: java.lang.String
	 **/
	@AuthAnonymous
	@RequestMapping(value = "/to/view",method = RequestMethod.GET)
	public String toView(Model model, Paging page, SearchVo searchVo){
		// 查询账单记录
		Query<BillResultVo> queryBill = new Query(page);
		queryBill.setCondition(searchVo);
		billService.queryBillList(queryBill);
		List<Type> typeList = typeService.searchAllType();
		model.addAttribute("typeList", typeList);
		model.addAttribute("queryBill", queryBill);
		model.addAttribute("searchVo", searchVo);
		if (searchVo.getCustomerId() == null && searchVo.getToken() == null) {
			searchVo.setCustomerId(operator.fetchUserId());
			model.addAttribute("userName", operator.fetchUserName());
			model.addAttribute("customerId",operator.fetchUserId());
		} else {
			model.addAttribute("customerId",searchVo.getCustomerId());
		}
		
		return "bill_view";
	}


	@AuthAnonymous
	@ResponseBody
	@RequestMapping(value = "/text",method = RequestMethod.GET)
	public ResponseResult text(Paging page, SearchVo searchVo){
		ResponseResult result = new ResponseResult(); 
		Query<BillResultVo> queryBill = new Query(page);
		searchVo.setCustomerId(operator.fetchUserId());
		queryBill.setCondition(searchVo);
		billService.queryBillList(queryBill);
		result.setData(queryBill);
		return result;
	}
	
	/**
	 * 去到添加账单记录的页面
	 * author: 900045
	 * date: 2021-09-29 11:47:19
	 * throws 
	 * @param model: 
	 * return: java.lang.String
	 **/
	@AuthAnonymous
	@RequestMapping(value = "/to/add",method = RequestMethod.GET)
	public String toAddBill(Model model){
		List<Mode> modeList = modeService.searchAllMode();
		model.addAttribute("modeList", modeList);
		List<Type> typeList = typeService.searchAllType();
		model.addAttribute("typeList", typeList);
		List<Source> sourceList = sourceService.searchAllSource();
		model.addAttribute("sourceList", sourceList);
		return "bill_add";
	}

	/**
	 * 去到时间控件页面 -- test
	 * author: 900045
	 * date: 2021-10-08 11:48:12
	 * throws 
	
	 * return: java.lang.String
	 **/
	@AuthAnonymous
	@RequestMapping(value = "/to/date",method = RequestMethod.GET)
	public String toDate(){
		return "datetime";
	}

	/**
	 * 添加账单记录
	 * author: 900045
	 * date: 2021-09-29 11:47:07
	 * throws 
	 * @param bill: 
	 * @param result: 
	 * return: com.zmm.common.base.model.Result
	 **/
	@ResponseBody
	@Interface(description = "添加账单", version = "1.0.0",respClass = Result.class )
	@PostMapping(value = "/do/add")
	public Result doAddBill(@Validated({AddGroup.class}) @Param(description = "实体对象", isClass = true)Bill bill, BindingResult result){
		// step1.表达校验
		if (result.hasErrors()){
			return BindingResultUtil.paramVerify(result);
		}
		// step2.获取用户ID
		bill.setCustomerId(operator.fetchUserId());
		
		// step3.执行业务
		try {
			billService.saveBill(bill);
		} catch (Exception e){
			return Result.error(ResultCode.FAIL.getCode(),e.getMessage());
		}
		return Result.ok();
	}

	/**
	 * 更新ID 获取账单详情
	 * author: 900045
	 * date: 2021-10-08 16:38:44
	 * throws
	 * return: com.zmm.common.base.model.Result
	 **/
	@Deprecated
	@RequestMapping(value = "/to/findOne",method = RequestMethod.GET)
	public String getFindBillByRecordId(){
		return "bill_update";
		//https://gitee.com/root121toor/spring-boot-accounting-system/blob/master/src/main/resources/templates/bill/update.html
	}


	/**
	 * 去到更新账单页面
	 * description:
	 * author: Zebulon
	 * date: 2021-10-08 20:14:38
	 * @param model:
	 * @param recordId:
	 * return: java.lang.String
	 **/
	@RequestMapping(value = "/to/update",method = RequestMethod.GET)
	public String toUpdateBill(Model model,Integer recordId){
		Bill bill = billService.findOneBill(recordId);
		List<Mode> modeList = modeService.searchAllMode();
		List<Type> typeList = typeService.searchAllType();
		List<Source> sourceList = sourceService.searchAllSource();
		model.addAttribute("modeList", modeList);
		model.addAttribute("typeList", typeList);
		model.addAttribute("sourceList", sourceList);
		model.addAttribute("bill", bill);
		return "bill_update";
	}
	
	/**
	 * 更新账单信息
	 * author: 900045
	 * date: 2021-10-08 16:38:34
	 * throws 
	 * @param bill: 
	 * @param result: 
	 * return: com.zmm.common.base.model.Result
	 **/
	@ResponseBody
	@PostMapping(value = "/do/update")
	public Result doUpdateBill(@Validated({UpdateGroup.class}) Bill bill, BindingResult result){
		// step1.表达校验
		if (result.hasErrors()){
			return BindingResultUtil.paramVerify(result);
		}
		// step2.执行业务
		return updateBill(bill);
	}

	private Result updateBill(@Validated({UpdateGroup.class}) Bill bill) {
		try {
			billService.modifyBill(bill);
		} catch (Exception e) {
			return Result.error(ResultCode.FAIL.getCode(), e.getMessage());
		}
		return Result.ok();
	}

	/**
	 * 去到账单消耗统计详情 默认查询本月
	 * description:
	 * author: Zebulon
	 * date: 2021-10-08 20:18:34
	 * return: java.lang.String
	 **/
	@GetMapping(value = "/to/detail")
	public String findBillDetail(Model model, DetailParamVo detailParamVo){
		Integer scope = getScope(detailParamVo);
		Integer customerId = operator.fetchUserId();
		detailParamVo.setCustomerId(customerId);
		BillConsumeDetailVo detailVo = billService.findBillDetail(scope,detailParamVo);
		
		packModel(model, detailParamVo, operator.fetchUserName(), detailVo);
		return "bill_detail";
	}

	private void packModel(Model model, DetailParamVo detailParamVo, String userName, BillConsumeDetailVo detailVo) {
		List<Type> typeList = typeService.searchAllType();
		model.addAttribute("typeList", typeList);
		model.addAttribute("detailVo", detailVo);
		model.addAttribute("userName", userName);
		model.addAttribute("detailParamVo",detailParamVo);
	}

	/**
	 * 获取时间方式
	 * author: 900045
	 * date: 2021-10-11 14:07:25
	 * throws 
	 * @param detailParamVo: 
	 * return: java.lang.Integer
	 **/
	private Integer getScope(DetailParamVo detailParamVo) {
		// 默认查询本月
		Integer scope;
		if (detailParamVo.getStartTime() == null || "".equals(detailParamVo.getStartTime())) {
			if (detailParamVo.getEndTime() == null || "".equals(detailParamVo.getEndTime())) {
				// 都为空 默认查询当前时间
				scope = 1;
			} else {
				// 开始时间为空 结束时间不为空 截止到结束时间
				scope = 2;
			}
			
		} else {
			if (detailParamVo.getEndTime() == null || "".equals(detailParamVo.getEndTime())) {
				// 开始时间不为空 结束时间为空 开始时间 ~ 当前时间
				scope = 3;
			} else {
				// 开始时间 ~ 结束时间
				scope = 4;
			}
		}
		return scope;
	}

	@AuthAnonymous
	@GetMapping(value = "/to/detail2")
	public String findBillDetail2(Model model, DetailParamVo detailParamVo){
		Integer scope = getScope(detailParamVo);
		BillConsumeDetailVo detailVo = billService.findBillDetail(scope,detailParamVo);
		String token = detailParamVo.getToken();
		if (StringUtils.isEmpty(token)) {
			model.addAttribute("msg","用户Token不正确");
			return "error";
		}
		Object object = getUserFromRedis(token);
		if (object == null){
			model.addAttribute("msg","用户Token不正确");
			return "error";
		}
		UserForAuth user = (UserForAuth) object;
		if (ObjectUtils.isEmpty(user)){
			model.addAttribute("msg","用户不存在");
			return "error";
		}
		detailParamVo.setCustomerId(user.getUserId());
		packModel(model, detailParamVo, user.getUserName(),detailVo);
		return "bill_detail";
	}
	
	/**
	 * 删除账单记录
	 * description:
	 * author: Zebulon
	 * date: 2021-10-08 20:15:01
	 * @param recordId:
	 * return: com.zmm.common.base.model.Result
	 **/
	@ResponseBody
	@PostMapping(value = "/del/bill")
	public Result delBillByRecordId(Integer recordId){
		Bill bill = new Bill();
		bill.setDeleteFlag(0);
		bill.setRecordId(recordId);
		return updateBill(bill);
	}

	// 查询当月的总消耗
	// SELECT SUM(IF(mode=1,-money,+money)) FROM `bill` WHERE date LIKE '2021-10-%';
}
